
class Words{
    /**
     * 
     * @param {number} code 
     * @param {number} prefix 
     * @param {number} suffix 
     */
    constructor(code,prefix,suffix){
        /**编码*/
        this.code=code;
        /**前缀*/
        this.prefix=prefix;
        /**后缀*/
        this.suffix=suffix;
        
        Object.defineProperty(this,"value",{
            get(){
                if(this.code<=0xff){
                    return this.code;
                }else{
                    return [this.prefix,this.suffix]
                }
            }
        })
    }
}
/**清除标志 */
const clear=new Words(0x100);
/**结束标志 */
const finish=new Words(0x101);
/**
 * 压缩
 * @param {number[]} source 
 */
function encoding(source){
    
    arr=source;
    //console.log(arr);
    
    /**字典 */
    let dic=[];
    for(let i=0;i<=0xff;i++){
        dic.push(new Words(i));
    }
    dic.push(clear);
    dic.push(finish);
    /**查字典 */
    function find(pre,suf){
        for(i=pre;i<dic.length;i++){
            let word=dic[i];
            if(word.prefix===pre && word.suffix===suf){
                return word;
            }
        }
    }
    
    let prefix=arr[0],suffix=undefined,word=undefined;
    let result=[];//压缩结果 0x000~0xfff的编码
    
    for(let i=1;i<arr.length;i++){
        suffix=arr[i];
        word=find(prefix,suffix);
        if(word) {
            prefix=word.code;
        }else{
            result.push(prefix);
            word=new Words(dic.length,prefix,suffix);
            dic.push(word);
            prefix=suffix;
            if(dic.length==0xfff){
                //清除字典
                result.push(0x100)
                dic.length=0x102;
            }
        }
    }
    result.push(prefix);
    //结束
    if(result.length%2==1)result.push(0x101);
    /** 2个code转成3byte */
    function output(result){
        let bytes=[];
        for(let i=0;i<result.length;i+=2){
            let tmp=result[i]<<12;
            tmp=tmp|result[i+1]
            bytes.push(tmp>>16 & 0xff);
            bytes.push(tmp>>8 & 0xff);
            bytes.push(tmp & 0xff);
        }
        return bytes;
    }

    return output(result);
    
}
/**
 * 解压
 * @param {number[]} source 
 */
function decoding(source){
    source=makeCode(source);
    let arr=[];
    //console.log(source)
    /**字典 */
    let dic=[];
    for(let i=0;i<=0xff;i++){
        dic.push(new Words(i));
    }
    dic.push(clear);
    dic.push(finish);
    
    let prefix=source[0],suffix=undefined,word=undefined;
    output(prefix);
    let p=0;
    for(let i=1;i<source.length;i++){
        suffix=source[i];
        if(suffix==0x100){
            dic.length=0x102;
            i++
            prefix=source[i];
            output(prefix)
        }else if(suffix==0x101){
            break;
        }else{
            word=dic[suffix];
            if(word){
                dic.push(new Words(dic.length,prefix,basePrefix(suffix)));
            }else{
                dic.push(new Words(suffix,prefix,basePrefix(prefix)));
            }
            prefix=suffix;
            output(suffix);
        }
    }
    //console.log(dic.filter( e =>e.code>0xff))
    //console.log(arr)
    
    return arr;
    function output(code){
        if(code<=0xff){
            arr.push(code);
        }else{
            let word=dic[code];
            output(word.prefix);
            arr.push(word.suffix);
        }
    }

    function basePrefix(code){
        while(code>0xff){
            code=dic[code].prefix;
        }
        return code;
    }
    /**3个字节组成2个code，code大小12位 */
    function makeCode(source){
        let arr=[];
        for(let i=0;i<source.length;i+=3){
            arr.push((source[i]<<8|source[i+1])>>4);
            arr.push((source[i+1]<<8|source[i+2]) & 0xfff);
        }
        return arr;
    }


}